package com.example.springbootusecase.multiThread;

import java.util.concurrent.Callable;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.ForkJoinPool;

/**
 * @author Think
 */
public class ForkAndJoinDemo {
    public static void main(String[] args) {
        ForkJoinPool pool = new ForkJoinPool(4);

        // 定义任务
        //extends ForkJoinTask
        //RecursiveAction 任务：task1、task2 和 task3 都是 RecursiveAction 的实例，它们代表了要执行的工作单元。这些任务本身并不是线程，而是可以被线程池中的工作线程执行的任务对象
        RecursiveAction task1 = new RecursiveAction() {
            @Override
            protected void compute() {
                System.out.println(Thread.currentThread().getName() + " Executing Task One");
            }
        };

        RecursiveAction task2 = new RecursiveAction() {
            @Override
            protected void compute() {
                //当在一个任务内部调用另一个任务的invoke()时，当前任务会暂停执行，直到被调用的任务完成。这确保了任务按照特定的顺序执行
                task1.fork(); // 确保task1先执行
                task1.join();
                System.out.println(Thread.currentThread().getName() + " Executing Task Two");
            }
        };

        RecursiveAction task3 = new RecursiveAction() {
            @Override
            protected void compute() {
                task2.fork(); // 确保task2先执行
                task2.join();
                System.out.println(Thread.currentThread().getName() + " Executing Task Three");
            }
        };

        // 提交并等待完成
        //阻塞当前线程，直到task3及其依赖的所有任务都完成
        //方法会阻塞当前线程，直到task3及其依赖的所有任务都完成。由于task3在其compute()方法中调用了task2.invoke()，而task2又调用了task1.invoke()，所以实际上，task1会首先被执行，然后是task2，最后是task3。这就实现了任务的顺序执行。
        //当你调用 pool.invoke(task3) 时，ForkJoinPool 会从它的线程池中选择一个可用的工作线程来执行 task3
        //task1、task2 和 task3 的执行是由 ForkJoinPool 中的工作线程来完成的。具体来说，task1 会在某个工作线程上执行，完成后，task2 会在另一个（或同一个）工作线程上执行，最后 task3 也会在某个工作线程上执行。
        pool.invoke(task3);
        pool.shutdown();

        
        class A implements Callable{

            @Override
            public Object call() throws Exception {
                return null;
            }
        }
    }
}